package com.kevinwu.zookeepertask.taskone.handler;

import com.kevinwu.zookeepertask.taskone.service.UserServiceImpl;
import com.kevinwu.zookeepertask.taskone.utils.RpcRequest;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Map;

@Component
public class UserServerHandler extends ChannelInboundHandlerAdapter  {

    /**
     * 接收请求后处理
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        RpcRequest request  = (RpcRequest) msg;
        Long startTime = System.currentTimeMillis();
        try {
            Object handler = handler(ctx,request);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        Long finishTime = System.currentTimeMillis();
        Long actTime = finishTime - startTime;
        //向zookeeper注册响应节点或者更新节点的值 /response/ip:port  值为当前时间
        UserServiceImpl.responseNode(String.valueOf(actTime));
        ctx.writeAndFlush("8092服务success");
    }

    /**
     * 反射处理以及返回值
     * @param request
     * @return
     * @throws Throwable
     */
    private Object handler(ChannelHandlerContext ctx, RpcRequest request) throws Throwable {

        String className = request.getClassName();
        String methodName = request.getMethodName();
        Class<?>[] parameterTypes = request.getParameterTypes();
        Object[] parameters = request.getParameters();

        //反射调用方法
        Class<?> clazz  = Class.forName(className);
        Map<String, ?> beansMap = SpringContextUtil.getBeansOfType(clazz);
        //调用方法
        Method method = clazz.getMethod(methodName, parameterTypes);
        Object obj = null;
        for (Map.Entry<String, ?> stringEntry : beansMap.entrySet()) {
            Object bean = stringEntry.getValue();
            obj = method.invoke(bean,parameters);
        }
        return obj;
    }
}
